/* Copyright 2009
 *
 * This program and the accompanying materials
 * are made available under the terms of the
 * Eclipse Public License v1.0 which accompanies
 * this distribution, and is available at
 *
 * 		http://www.eclipse.org/legal/epl-v10.html
 *
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
 * OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * Contributors:
 * 	   IBM Corporation - initial API and implementation for JDT/DLTK
 *     Sean W. Quinn - initial adoption for use with PHP from various sources.
 */
package org.eclipse.php.internal.ui.preferences.formatter;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.dltk.compiler.util.Util;
import org.eclipse.dltk.ui.formatter.IFormatterControlManager;
import org.eclipse.dltk.ui.preferences.ControlBindingManager;
import org.eclipse.dltk.ui.preferences.FieldValidators;
import org.eclipse.dltk.ui.preferences.IPreferenceDelegate;
import org.eclipse.dltk.ui.util.IStatusChangeListener;
import org.eclipse.dltk.ui.util.SWTFactory;
import org.eclipse.php.internal.ui.util.ReflectionUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

/**
 * @author Sean W. Quinn (swquinn@gmail.com)
 *
 */
public class PHPFormatterControlManager implements IFormatterControlManager, IStatusChangeListener {

  private final IPreferenceDelegate delegate;
  private final ControlBindingManager bindingManager;
  private final IStatusChangeListener listener;
  private final Map<Control, Label> labelAssociations = new HashMap<Control, Label>();

  /**
   *
   * @return
   */
  protected ControlBindingManager getBindingManager() {
    //return ReflectionUtils.getFieldValue(this, "bindingManager");
    return bindingManager;
  }

  /**
   *
   * @return
   */
  protected Map<Control, Label> getLabelAssociations() {
    //return (Map<Control, Label>) ReflectionUtils.getFieldValue(this, "labelAssociations");
    return labelAssociations;
  }

  public PHPFormatterControlManager(final IPreferenceDelegate delegate, final IStatusChangeListener listener) {
    this.delegate = delegate;
    this.bindingManager = new ControlBindingManager(delegate, this);
    this.listener = listener;
  }

  public Button createCheckbox(Composite parent, Object key, String text) {
    return createCheckbox(parent, key, text, 1);
  }

  public Button createCheckbox(Composite parent, Object key, String text, int hspan) {
    Button button = SWTFactory.createCheckButton(parent, text, null, false, hspan);
    bindingManager.bindControl(button, key, null);
    return button;
  }

  public Combo createCombo(Composite parent, Object key, String label, String[] items) {
    return createCombo(parent, key, label, items, 1);
  }

  public Combo createCombo(Composite parent, Object key, String label, String[] items, final int hspan) {
    final int labelSpan = (hspan > 2) ? hspan - 1 : 1;
    final Label labelControl = SWTFactory.createLabel(parent, label, labelSpan);
    Combo combo = SWTFactory.createCombo(parent, SWT.READ_ONLY | SWT.BORDER, 1, items);
    bindingManager.bindControl(combo, key);
    registerAssociatedLabel(combo, labelControl);
    return combo;
  }

  public Combo createCombo(Composite parent, Object key, String label, String[] itemValues, String[] itemLabels) {
    return createCombo(parent, key, label, itemValues, itemLabels, 1);
  }

  public Combo createCombo(Composite parent, Object key, String label, String[] itemValues, String[] itemLabels, final int hspan) {
    final int labelSpan = (hspan > 2) ? hspan - 1 : 1;
    //final int spacerSpan = (hspan > 2) ? hspan - 1 : 1;
    //SWTFactory.createHorizontalSpacer(parent, spacerSpan);

    final Label labelControl = SWTFactory.createLabel(parent, label, labelSpan);
    Combo combo = SWTFactory.createCombo(parent, SWT.READ_ONLY | SWT.BORDER, 1, itemLabels);
    bindingManager.bindControl(combo, key, itemValues);
    registerAssociatedLabel(combo, labelControl);
    return combo;
  }

  public Text createNumber(Composite parent, Object key, String label) {
    return createNumber(parent, key, label, 1);
  }

  public Text createNumber(final Composite parent, final Object key, final String label, final int hspan) {
    final int labelSpan = (hspan > 2) ? hspan - 1 : 1;
    final Label labelControl = SWTFactory.createLabel(parent, label, labelSpan);
    Text text = SWTFactory.createText(parent, SWT.BORDER, 1, Util.EMPTY_STRING);
    getBindingManager().bindControl(text, key, FieldValidators.POSITIVE_NUMBER_VALIDATOR);
    registerAssociatedLabel(text, labelControl);
    return text;
  }

  /**
   * @param control
   * @param label
   */
  private void registerAssociatedLabel(Control control, Label label) {
    labelAssociations.put(control, label);
  }

  public void enableControl(Control control, boolean enabled) {
    control.setEnabled(enabled);
    final Label label = (Label) labelAssociations.get(control);
    if (label != null) {
      label.setEnabled(enabled);
    }
  }

  private final ListenerList initListeners = new ListenerList();

  public void addInitializeListener(IInitializeListener listener) {
    initListeners.add(listener);
  }

  public void removeInitializeListener(IInitializeListener listener) {
    initListeners.remove(listener);
  }

  private boolean initialization;

  public void initialize() {
    initialization = true;
    try {
      bindingManager.initialize();
      final Object[] listeners = initListeners.getListeners();
      for (int i = 0; i < listeners.length; ++i) {
        ((IInitializeListener) listeners[i]).initialize();
      }
    }
    finally {
      initialization = false;
    }
    listener.statusChanged(bindingManager.getStatus());
  }

  public void statusChanged(IStatus status) {
    if (!initialization) {
      listener.statusChanged(status);
    }
  }

  public boolean getBoolean(Object key) {
    return delegate.getBoolean(key);
  }

  public String getString(Object key) {
    return delegate.getString(key);
  }

  public void setBoolean(Object key, boolean value) {
    delegate.setBoolean(key, value);
  }

  public void setString(Object key, String value) {
    delegate.setString(key, value);
  }

  /**
   *
   * @param manager
   * @return
   */
  public static PHPFormatterControlManager newInstance(final IFormatterControlManager manager) {
    final IPreferenceDelegate delegate = (IPreferenceDelegate) ReflectionUtils.getFieldValue(manager, "delegate");
    final IStatusChangeListener listener = (IStatusChangeListener) ReflectionUtils.getFieldValue(manager, "listener");
    return new PHPFormatterControlManager(delegate, listener);
  }
}
